﻿namespace Pp.Repository
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Linq;
    using System.Web;
    using Core;
    using Core.Extentions;
    using Core.File;
    using Domain.Model;
    using Dto;
    using Globalization;
    using NHibernate;
    using NHibernate.Criterion;

    public class ProjectRepository : BaseRepository<Project>
    {
        public UserRepository UserRepository;
        public ProjectCategoryRepository ProjectCategoryRepository;

        public ProjectRepository(ISession session, HttpServerUtilityBase server)
            : base(session, server)
        {
            UserRepository = new UserRepository(session, server);
            ProjectCategoryRepository = new ProjectCategoryRepository(session, server);
        }

        public PageList<ProjectDto> AllProject(int? page, int pageSize, Guid? category, string searchStr)
        {
            string urlPre = "/Home/Index";
            var criteria =
                Session.CreateCriteria(typeof(Project));
            if (category.HasValue)
            {
                criteria = criteria.CreateAlias("Category", "cat")
                .Add(Restrictions.Eq("cat.Id", category));
                urlPre += "?c=" + category.Value;
            }
            if (!string.IsNullOrEmpty(searchStr))
            {
                criteria = criteria.Add(Restrictions.Like("Name", searchStr, MatchMode.Anywhere));
                if (urlPre.Contains("?"))
                    urlPre += "&&search=" + searchStr;
                else
                    urlPre += "?search=" + searchStr;
            }
            var pageStart = page.HasValue ? page.Value : 0;
            var maxCount = CriteriaTransformer.TransformToRowCount(criteria).UniqueResult<int>();

            var projects = criteria
                .AddOrder(Order.Desc("CreateDate"))
                .SetFirstResult(pageStart * pageSize)
                .SetMaxResults(pageSize);

            var list = projects.List<Project>().Select(project => project.ToDto()).ToList();
            return new PageList<ProjectDto> { List = list, PageInfo = new PageInfo { ListCount = maxCount, PageNumber = pageStart, PageSize = pageSize, UrlPrefix = urlPre } };
        }
        public Result NewProject(ProjectCreate createProject, string contextUser)
        {
            createProject.Description = Server.HtmlEncode(createProject.Description);

            var cat = ProjectCategoryRepository.Get(createProject.CategoryId);
            var user = UserRepository.GetByUsername(contextUser);
            var proje = new Project
                            {
                                Description = createProject.Description,
                                SmallDescription = createProject.SmallDescription,
                                Name = createProject.Name,
                                User = user,
                                Category = cat,
                                Likes = new List<Like>(),
                                AllowAngelRequest = createProject.AllowAllowRequest,
                                ProjectCosting = createProject.ProjectCosting,
                                SignatureCollect =
                                    !string.IsNullOrEmpty(createProject.SignatureCollect)
                                        ? createProject.SignatureCollect.Trim()
                                        : null
                            };
            Save(proje);
            if (createProject.ImageFile != null)
            {
                const string linkRoot = "/Content/Upload/Project/";
                var saveResult = SavePicture(linkRoot, createProject.ImageFile, ImageSize.smallSize, proje.Id);
                if (!saveResult.Success) return Result.AsError(saveResult.Error);
                saveResult = SavePicture(linkRoot, createProject.ImageFile, ImageSize.mediumSize, proje.Id);
                if (!saveResult.Success) return Result.AsError(saveResult.Error);
                saveResult = SavePicture(linkRoot, createProject.ImageFile, ImageSize.largeSize, proje.Id);
                if (!saveResult.Success) return Result.AsError(saveResult.Error);
            }
            var message = CreateMail(Res.Label_Sahare_Project, MailType.NewProject, new List<MailModel>
                                                                                           {
                                                                                               new MailModel("ProjectId",proje.Id.ToString()),
                                                                                               new MailModel("ProjectName",proje.Name)
                                                                                           }, user.MailAdress).Data;
            foreach (var profileFollow in user.TheyFollows)
                message.To.Add(profileFollow.Follower.MailAdress);

            SendMail(message);
            return Result.AsSuccess();
        }
        public Result<int> Like(Guid? id, string name)
        {
            var user = UserRepository.GetByUsername(name);
            var proj = Get(id);
            if (proj == null || user == null)
                return Result<int>.AsError(Res.Information_Object_NoFound);
            if (proj.Likes.Where(d => d.Processor.Username == name).Count() > 0)
                return Result<int>.AsError(Res.Information_like_allready_exsist);
            var like = new ProjectLike
                           {
                               Project = proj,
                               Processor = user
                           };
            Session.Save(like);
            proj.Likes.Add(like);
            Update(proj);
            var count = proj.Likes.Count;
            return Result<int>.AsSuccess(count);
        }
        public Result<int> Dislike(Guid? id, string name)
        {
            var proj = Get(id);
            if (proj == null)
                return Result<int>.AsError(Res.Information_Object_NoFound);
            var like = proj.Likes.Where(d => d.Processor.Username == name).SingleOrDefault();
            if (like == null)
                return Result<int>.AsError(Res.Information_like_no_already_exsist);
            Session.Delete(like);
            proj.Likes.Remove(like);
            Update(proj);
            var count = proj.Likes.Count;
            return Result<int>.AsSuccess(count);
        }

        public Result<ProjectDetailDto> GetDetail(Guid? id)
        {
            if (!id.HasValue) return Result<ProjectDetailDto>.AsError(Res.Information_invalid_id);
            var project = Get(id.Value);
            if (project == null) return Result<ProjectDetailDto>.AsError(Res.Information_could_not_be_reached_project_detail);
            var detail = project.ToDetailDto();
            return Result<ProjectDetailDto>.AsSuccess(detail);
        }

        public ProjectEdit GetProjectEdit(Guid? id)
        {
            var edit = Get(id);
            if (edit == null) throw new Exception(Res.Information_Object_NoFound);
            return edit.ToEditDto();
        }

        public Result EditProject(ProjectEdit projectEdit, string name)
        {
            projectEdit.Description = Server.HtmlEncode(projectEdit.Description);
            var project = Get(projectEdit.Id);
            if (project == null) throw new Exception(Res.Message_Project_No_Found);
            project.Name = projectEdit.Name;
            project.Description = projectEdit.Description;
            project.Category = ProjectCategoryRepository.Get(projectEdit.CategoryId);
            project.AllowAngelRequest = projectEdit.AllowAllowRequest;
            project.SmallDescription = projectEdit.SmallDescription;
            project.ProjectCosting = projectEdit.ProjectCosting;
            project.SignatureCollect = !string.IsNullOrEmpty(projectEdit.SignatureCollect) ? projectEdit.SignatureCollect.Trim() : string.Empty;
            Update(project);
            if (projectEdit.ImageFile != null)
            {
                const string linkRoot = "/Content/Upload/Project/";
                var saveResult = SavePicture(linkRoot, projectEdit.ImageFile, ImageSize.smallSize, project.Id);
                if (!saveResult.Success) return Result.AsError(saveResult.Error);
                saveResult = SavePicture(linkRoot, projectEdit.ImageFile, ImageSize.mediumSize, project.Id);
                if (!saveResult.Success) return Result.AsError(saveResult.Error);
                saveResult = SavePicture(linkRoot, projectEdit.ImageFile, ImageSize.largeSize, project.Id);
                if (!saveResult.Success) return Result.AsError(saveResult.Error);
            }
            var message = CreateMail(Res.Label_Share_Project, MailType.NewProject, new List<MailModel>
                                                                                           {
                                                                                               new MailModel("ProjectId",project.Id.ToString()),
                                                                                               new MailModel("ProjectName",project.Name)
                                                                                           }, project.User.MailAdress).Data;
            foreach (var profileFollow in project.User.TheyFollows)
                message.To.Add(profileFollow.Follower.MailAdress);
            foreach (var profileFollow in project.Follows)
                message.To.Add(profileFollow.Follower.MailAdress);
            SendMail(message);
            return Result.AsSuccess();
        }

        public Result<IList<Project>> GetAllById(Guid? id)
        {
            var x = BaseCriteria.Add(Restrictions.Eq("Id", id));
            return Result<IList<Project>>.AsSuccess(x.List<Project>().ToList());
        }
        public Result DeleteById(Guid? id)
        {
            var project = Get(id);
            if (project == null) return Result.AsError(Res.Information_Project_NoFound_For_Remove);
            return Delete(project);
        }
    }
}
